
// 创建虚拟DOM节点（VNode）的函数，简单模拟
function createVNode(tag, props, children) {
    return {
        tag,
        props,
        children,
        key: props?.key || null
    };
}

// 判断两个VNode是否是相同类型节点（这里简单根据tag和key判断）
function isSameVNodeType(n1, n2) {
    return n1.tag === n2.tag && n1.key === n2.key;
}

// 挂载单个VNode到真实DOM容器中
function mountVNode(vnode, container) {
    const el = document.createElement(vnode.tag);
    if (vnode.props) {
        for (const key in vnode.props) {
            el.setAttribute(key, vnode.props[key]);
        }
    }
    if (vnode.children) {
        if (Array.isArray(vnode.children)) {
            vnode.children.forEach(child => {
                mountVNode(child, el);
            });
        } else {
            el.textContent = vnode.children;
        }
    }
    container.appendChild(el);
    vnode.el = el;
    return el;
}

// 卸载VNode对应的真实DOM元素
function unmountVNode(vnode) {
    if (vnode.el && vnode.el.parentNode) {
        vnode.el.parentNode.removeChild(vnode.el);
    }
}

// 对比新旧子节点（核心的diff逻辑，简化版）
function patchKeyedChildren(c1, c2, container) {
    let i = 0;
    let e1 = c1.length - 1;
    let e2 = c2.length - 1;

    // 同时从头部开始比较
    while (i <= e1 && i <= e2) {
        const n1 = c1[i];
        const n2 = c2[i];
        if (isSameVNodeType(n1, n2)) {
            patch(n1, n2, n1.el.parentNode);
        } else {
            break;
        }
        i++;
    }

    // 同时从尾部开始比较
    while (e1 >= i && e2 >= i) {
        const n1 = c1[e1];
        const n2 = c2[e2];
        if (isSameVNodeType(n1, n2)) {
            patch(n1, n2, n1.el.parentNode);
        } else {
            break;
        }
        e1--;
        e2--;
    }

    if (i > e1) {
        // 如果旧节点先遍历完，说明新节点有新增的，依次挂载新节点
        if (i <= e2) {
            const nextPos = e1 + 1;
            const anchor = e2 + 1 < c2.length ? c2[e2 + 1].el : null;
            while (i <= e2) {
                mountVNode(c2[i], container, anchor);
                i++;
            }
        }
    } else if (i > e2) {
        // 如果新节点先遍历完，说明旧节点有多余的，依次卸载旧节点
        while (i <= e1) {
            unmountVNode(c1[i]);
            i++;
        }
    } else {
        // 中间部分的复杂比较和处理，构建新旧节点的映射关系，基于key来判断复用、移动等情况
        const s1 = i;
        const s2 = i;
        const keyToNewIndexMap = new Map();
        for (let i = s2; i <= e2; i++) {
            const nextChild = c2[i];
            keyToNewIndexMap.set(nextChild.key, i);
        }
        let j;
        const toBePatched = e2 - s2 + 1;
        const newIndexToOldIndexMap = new Array(toBePatched).fill(0);
        for (let i = s1; i <= e1; i++) {
            const prevChild = c1[i];
            let newIndex = keyToNewIndexMap.get(prevChild.key);
            if (newIndex === undefined) {
                // 旧节点在新节点中找不到对应的key，说明该节点需要被卸载
                unmountVNode(prevChild);
            } else {
                newIndexToOldIndexMap[newIndex - s2] = i;
            }
        }
        for (let i = s2; i <= e2; i++) {
            const nextChild = c2[i];
            let oldIndex = newIndexToOldIndexMap[i - s2];
            if (oldIndex === 0) {
                // 如果旧索引为0，说明是新增节点，进行挂载
                const anchor = i < e2 ? c2[i + 1].el : null;
                mountVNode(nextChild, container, anchor);
            } else {
                const prevChild = c1[oldIndex];
                if (isSameVNodeType(prevChild, nextChild)) {
                    // 如果是相同类型节点，进行更新
                    patch(prevChild, nextChild, prevChild.el.parentNode);
                } else {
                    // 如果类型不同，先卸载旧节点，再挂载新节点
                    unmountVNode(prevChild);
                    const anchor = i < e2 ? c2[i + 1].el : null;
                    mountVNode(nextChild, container, anchor);
                }
            }
        }
    }
}

// 对比更新两个VNode（入口函数）
function patch(n1, n2, container) {
    if (n1 === n2) {
        return;
    }
    if (!n1) {
        mountVNode(n2, container);
    } else if (!n2) {
        unmountVNode(n1);
    } else if (isSameVNodeType(n1, n2)) {
        if (n1.tag === 'text') {
            if (n1.children !== n2.children) {
                n1.el.textContent = n2.children;
            }
        } else {
            const el = n1.el;
            patchProps(n1.props, n2.props, el);
            patchChildren(n1, n2, el);
        }
    } else {
        unmountVNode(n1);
        mountVNode(n2, container);
    }
}

// 对比更新节点属性
function patchProps(oldProps, newProps, el) {
    if (oldProps) {
        for (const key in oldProps) {
            if (!newProps || !(newProps[key])) {
                el.removeAttribute(key);
            }
        }
    }
    if (newProps) {
        for (const key in newProps) {
            if (oldProps[key] !== newProps[key]) {
                el.setAttribute(key, newProps[key]);
            }
        }
    }
}

// 对比更新子节点（根据子节点类型调用不同的处理逻辑）
function patchChildren(n1, n2, el) {
    const c1 = n1.children;
    const c2 = n2.children;
    if (Array.isArray(c1) && Array.isArray(c2)) {
        patchKeyedChildren(c1, c2, el);
    } else if (Array.isArray(c1)) {
        while (c1.length) {
            unmountVNode(c1.pop());
        }
    } else if (Array.isArray(c2)) {
        mountVNode(c2[0], el);
    } else if (c1 !== c2) {
        if (c1) {
            n1.el.textContent = c2;
        } else {
            el.textContent = c2;
        }
    }
}

// 示例用法
const oldVNodes = [
    createVNode('div', { key: '1' }, 'old div 1'),
    createVNode('div', { key: '2' }, 'old div 2'),
    createVNode('div', { key: '3' }, 'old div 3')
];
const newVNodes = [
    createVNode('div', { key: '2' }, 'new div 2'),
    createVNode('div', { key: '3' }, 'new div 3'),
    createVNode('div', { key: '4' }, 'new div 4')
];

const app = document.getElementById('app');
console.log(oldVNodes[0]);

patch(null, oldVNodes, app);
patch(oldVNodes, newVNodes, app);

// let btn = document.getElementById('btn')
// btn.onclick = () => {
//     console.log('11');
    
//     patch(vnode2, vnode3)
// }
